package com.google.code.maven.plugin;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import org.apache.commons.io.FileUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;

/**
 * A properties extractor mojo
 * 
 * @goal extract
 * @description Extract maven 2 properties to properties.xml
 * @requiresDependencyResolution test
 */

public final class PropertiesMojo extends AbstractMojo {
	/**
	 * The set of dependencies required by the project
	 * 
	 * @parameter default-value="${project.artifacts}"
	 * @required
	 * @readonly
	 */
	private Set<Artifact> m_dependencies;

	/**
	 * Base directory of the project.
	 * 
	 * @parameter expression="${basedir}"
	 */
	private File m_baseDirectory;

	private Map<String, String> properties() {
		if (m_dependencies == null || m_dependencies.isEmpty()) {
			return Collections.emptyMap();
		}
		Map<String, String> properties = new TreeMap<String, String>();
		for (Artifact each : m_dependencies) {
			final String artifactId = each.getArtifactId().replace('-', '.');
			properties.put(artifactId, each.getVersion());
		}
		return properties;
	}

	public void execute() throws MojoExecutionException {
		try {
			new PropertiesWriter(new File(m_baseDirectory, "properties.xml"), properties()).write();
		} catch (Exception e) {
			getLog().debug(e);
			throw new MojoExecutionException(e.getMessage(), e);
		}
	}

	private static final class PropertiesWriter {
		private static final String VERSION_SUFIX = ".version";
		private static final String PROPERTIES = "properties";
		private static final String START = "<";
		private static final String CLOSE = ">";
		private static final String END = "</";
		private static final String INDENT = "\t";
		private static final String PROPERTIES_START = START + PROPERTIES + CLOSE;
		private static final String PROPERTIES_END = END + PROPERTIES + CLOSE;

		private final File m_file;
		private final Map<String, String> m_properties;
		private final List<String> m_lines;

		PropertiesWriter(File p_file, Map<String, String> p_properties) {
			m_file = p_file;
			m_properties = p_properties;
			m_lines = new ArrayList<String>(m_properties.size() + 2);
		}

		void write() throws IOException {
			FileUtils.writeLines(m_file, start().properties().end().m_lines);
		}

		private PropertiesWriter start() {
			m_lines.add(PROPERTIES_START);
			return this;
		}

		private PropertiesWriter properties() {
			for (Map.Entry<String, String> each : m_properties.entrySet()) {
				final String property = each.getKey() + VERSION_SUFIX;
				final String version = each.getValue();
				m_lines.add(INDENT + START + property + CLOSE + version + END + property + CLOSE);
			}
			return this;
		}

		private PropertiesWriter end() {
			m_lines.add(PROPERTIES_END);
			return this;
		}

	}
}
